package com.hsgene.common.util.exception;

import com.hsgene.common.util.web.access.exception.TokenException;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.core.Ordered;
import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.view.json.MappingJackson2JsonView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * 全局异常处理器
 *
 * @author wangbing
 * @version 1.0, 2018/7/5
 */
public class GlobalExceptionHandler implements HandlerExceptionResolver, Ordered {

    private final Logger logger = LogManager.getLogger(GlobalExceptionHandler.class);

    private static MappingJackson2JsonView jsonView = new MappingJackson2JsonView();

    public static final int DEFAULT_FAILED_STATUS = 9999;

    /**
     * 是否向前端返回服务器内部错误信息
     */
    private boolean globalExceptionEnable;

    public GlobalExceptionHandler(boolean globalExceptionEnable) {
        this.globalExceptionEnable = globalExceptionEnable;
    }

    @Override
    public ModelAndView resolveException(HttpServletRequest httpServletRequest,
                                         HttpServletResponse httpServletResponse, Object o, Exception e) {

        ModelAndView mav = new ModelAndView();
        mav.setView(jsonView);
        if (e instanceof RequiredParamException) {
            catchException(mav, CommonErrorCode.REQUIRED_PARAM, e);
        } else if (e instanceof IllegalParamException) {
            catchException(mav, CommonErrorCode.ILLEGAL_PARAM, e);
        } else if (e instanceof ValidationException) {
            catchException(mav, CommonErrorCode.VALIDATION_FAILED, e);
        } else if (e instanceof TokenException) {
            ErrorCode errorCode = ((TokenException) e).getErrorCode();
            mav.addObject("code", errorCode.getCode());
            mav.addObject("message", errorCode.getMessage());
            mav.addObject("desc", errorCode.getDescription());
        } else {
            logger.error("系统异常，错误信息：{}", e.getMessage(), e);
            mav.addObject("code", DEFAULT_FAILED_STATUS);
            mav.addObject("message", "system_error");
            if (!globalExceptionEnable) {
                mav.addObject("desc", "服务器内部错误");
            } else {
                mav.addObject("desc", "服务器内部错误:" + e.getMessage());
            }
        }
        return mav;
    }

    @Override
    public int getOrder() {
        return HIGHEST_PRECEDENCE;
    }

    private void catchException(ModelAndView mav, ErrorCode ec, Exception ex) {
        mav.addObject("code", ec.getCode());
        mav.addObject("message", ec.getMessage());
        mav.addObject("desc", ex.getMessage());
    }

}
